﻿using HartConfigTool.Commands.SystemCMDs;
using HartConfigTool.HARTCommands;
using HartConfigTool.UI;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace HartConfigTool.SerialPortUtil
{
    public class SerialPortsManager
    {
        private ICommand _currentCMD;
        private SerialPort _serialPort;
        private Control _debugMsgControl;
        private List<byte> _RxDataBuffer;
        public uint deviceID;

        public event EventHandler CommandCompleted;

        public TextBox debugTextBox;

        public SerialPortsManager()
        { 
            _serialPort = new SerialPort();
            _serialPort.BaudRate = 1200;
            _serialPort.Parity = Parity.Odd;
            _serialPort.StopBits = StopBits.One;
            _serialPort.DataBits = 8;

            _serialPort.DataReceived += new SerialDataReceivedEventHandler(OnDataReceived);

            _RxDataBuffer = new List<byte>();

            deviceID = 0xFFFFFFFF;
        }
        private async void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int bytesToRead = _serialPort.BytesToRead;
            byte[] buffer = new byte[bytesToRead];
            _serialPort.Read(buffer, 0, bytesToRead);

            WriteRxDataBuffer(buffer);

            if (_currentCMD is SystemCMDSetup)
            {
                await _currentCMD?.ParseResponse(buffer);
            }
            else
            {
                if (HARTProtocolV7.VerifyDataIsComplete(GetRxBufferData()) == true)
                {
                    await _currentCMD?.ParseResponse(buffer);
                    CommandCompleted?.Invoke(this, EventArgs.Empty);
                }
            }
        }
        public void SetCurrentCMD(ICommand cmd)
        { 
            _currentCMD = cmd;
        }
        public bool Open(string portName)
        {
            try
            {
                _serialPort.PortName = portName;
                _serialPort.Open();
            }
            catch 
            { 
                return false;
            }

            return true;
        }
        public void Close()
        {
            _serialPort?.Close();
        }
        public async Task SendCMD(byte[] cmdCode)
        {
            await Task.Run(() =>
            {
                if(_serialPort.IsOpen)
                {
                    _serialPort.RtsEnable = true;
                    _serialPort.Write(cmdCode, 0, cmdCode.Length);
                    Thread.Sleep(500);
                    _serialPort.RtsEnable = false;
                }
            });
        }
        public string[] GetSerialPortNames()
        { 
            return SerialPort.GetPortNames();
        }
        public void DebugMessage(string msg)
        {
            if (_debugMsgControl is TextBox)
            { 
                TextBox msgControl = (TextBox) _debugMsgControl;

                if (msgControl.InvokeRequired)
                {
                    msgControl.Invoke(new Action<string>(DebugMessage), msg);
                }
                else
                {
                    msgControl.AppendText(msg);
                }
            }
        }
        public void SetShowDebugMsgControl(Control control)
        {
            _debugMsgControl = control;
        }
        public void WriteRxDataBuffer(byte[] data)
        {
            _RxDataBuffer.AddRange(data);
        }
        public void RxDataClear()
        {
            _RxDataBuffer.Clear();
        }
        public byte[] GetRxBufferData()
        {
            return _RxDataBuffer.ToArray();
        }
        public void SetDebugMsgControl(TextBox txtBox)
        {
            debugTextBox = txtBox;
        }
    }
}
